#include "camera.h"
#include "matrix.h"

Camera::Camera()
    : origin_(Point(0,0,0)), lookAt_(Point(0, 0, -1)), up_(0, 1, 0)
{
}

Camera::Camera(const Point &origin, const Vector &lookAt, const Vector &up, const ProjectionPlane &projection_plane)
    : origin_(origin), lookAt_(origin + lookAt), up_(up), pplane_(projection_plane)
{
    k_ = (origin_ - lookAt_).normalize();
    i_ = vecprod(up_, k_);
    j_ = vecprod(k_, i_);
}

Camera::Camera(const Point &origin, const Point &lookAt, const Vector &up, const ProjectionPlane &projection_plane)
    : origin_(origin), lookAt_(lookAt), up_(up), pplane_(projection_plane)
{
    k_ = (origin - lookAt).normalize();
    i_ = vecprod(up_, k_);
    j_ = vecprod(k_, i_);
}

Camera::Camera(const Camera &c)
    : origin_(c.origin()), lookAt_(c.lookAt()), up_(c.up()), pplane_(c.projection_plane()),
    i_(c.i()), j_(c.j()), k_(c.k())
{
}

Camera& Camera::operator=(const Camera &c) {
    if( this != &c ) {
        origin_ = c.origin();
        lookAt_ = c.lookAt();
        up_ = c.up();
        i_ = c.i();
        j_ = c.j();
        k_ = c.k();
        pplane_ = c.projection_plane();
    }

    return *this;
}

const Point& Camera::origin() const {
    return origin_;
}

const Point& Camera::lookAt() const {
    return lookAt_;
}

const Vector& Camera::up() const {
    return up_;
}

const ProjectionPlane& Camera::projection_plane() const {
    return pplane_;
}

const Vector& Camera::i() const
{
    return i_;
}

const Vector& Camera::j() const
{
    return j_;
}

const Vector& Camera::k() const
{
    return k_;
}

GlFrame Camera::frame() const
{
    return GlFrame(origin_, i_, j_, k_);
}
